<template>
  <div class="json-to-class-container">
    <h1>JSON 转类定义</h1>
    <div class="tool-wrapper">
      <div class="input-section">
        <textarea v-model="inputJson" placeholder="请输入 JSON 数据" class="input-textarea"></textarea>
      </div>
      
      <div class="button-group">
        <select v-model="targetLanguage" class="language-select">
          <option value="java">Java</option>
          <option value="go">Go</option>
          <option value="typescript">TypeScript</option>
        </select>
        <button @click="convertJson" class="convert-button">转换</button>
        <button @click="copyToClipboard" class="copy-button">复制</button>
      </div>

      <div class="output-section">
        <pre><code id="code" :class="targetLanguage">{{ outputClass }}</code></pre>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, nextTick } from 'vue';
import hljs from 'highlight.js';
import 'highlight.js/styles/default.min.css';
import java from 'highlight.js/lib/languages/java';
import go from 'highlight.js/lib/languages/go';
import typescript from 'highlight.js/lib/languages/typescript';

// 注册语言
hljs.registerLanguage('java', java);
hljs.registerLanguage('go', go);
hljs.registerLanguage('typescript', typescript);

const inputJson = ref('');
const outputClass = ref('');
const targetLanguage = ref('java');

const convertJson = () => {
  try {
    const jsonObj = JSON.parse(inputJson.value);
    outputClass.value = generateClassDefinition(jsonObj, targetLanguage.value);
    console.log(outputClass.value);
    nextTick(() => {
      const codeElement = document.getElementById('code');
      if (codeElement) {
        // 先移除所有highlight相关的class
        codeElement.className = targetLanguage.value;
        // 强制重新渲染
        codeElement.innerHTML = outputClass.value;
        // 移除属性k
        codeElement.removeAttribute('data-highlighted');
      }
      // 重新应用highlight
      hljs.highlightElement(codeElement!);
    });
  } catch (error) {
    outputClass.value = '❌ 无效的JSON格式';
  }
};

const generateClassDefinition = (jsonObj: any, language: string): string => {
  // 这里实现具体的转换逻辑
  switch (language) {
    case 'java':
      return generateJavaClass(jsonObj);
    case 'go':
      return generateGoStruct(jsonObj);
    case 'typescript':
      return generateTypeScriptInterface(jsonObj);
    default:
      return '不支持的语言';
  }
};

// 实现具体的生成逻辑
const generateJavaClass = (jsonObj: any, className: string = 'AutoGenerated'): string => {
  let result = `public class ${className} {\n`;
  let subClasses = '';
  
  for (const key in jsonObj) {
    const value = jsonObj[key];
    if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
      const nestedClassName = capitalizeFirstLetter(key);
      result += `    private ${nestedClassName} ${key};\n`;
      subClasses += generateJavaClass(value, nestedClassName);
    } else if (Array.isArray(value) && value.length > 0) {
      const elementType = capitalizeFirstLetter(key) + 'Item';
      result += `    private List<${elementType}> ${key};\n`;
      if (typeof value[0] === 'object' && value[0] !== null) {
        subClasses += generateJavaClass(value[0], elementType);
      }
    } else {
      const type = getJavaType(value);
      result += `    private ${type} ${key};\n`;
    }
  }
  
  result += '}\n\n';
  return result + subClasses;
};

const generateGoStruct = (jsonObj: any, structName: string = 'AutoGenerated'): string => {
  let result = `type ${structName} struct {\n`;
  let subStructs = '';
  
  for (const key in jsonObj) {
    const value = jsonObj[key];
    if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
      const nestedStructName = capitalizeFirstLetter(key);
      result += `    ${nestedStructName} ${nestedStructName} \`json:"${key}"\`\n`;
      subStructs += generateGoStruct(value, nestedStructName);
    } else if (Array.isArray(value) && value.length > 0) {
      const elementType = capitalizeFirstLetter(key) + 'Item';
      result += `    ${capitalizeFirstLetter(key)} []${elementType} \`json:"${key}"\`\n`;
      if (typeof value[0] === 'object' && value[0] !== null) {
        subStructs += generateGoStruct(value[0], elementType);
      }
    } else {
      const type = getGoType(value);
      result += `    ${capitalizeFirstLetter(key)} ${type} \`json:"${key}"\`\n`;
    }
  }
  
  result += '}\n\n';
  return result + subStructs;
};

const generateTypeScriptInterface = (jsonObj: any, interfaceName: string = 'AutoGenerated'): string => {
  let result = `interface ${interfaceName} {\n`;
  let subInterfaces = '';
  
  for (const key in jsonObj) {
    const value = jsonObj[key];
    if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
      const nestedInterfaceName = capitalizeFirstLetter(key);
      result += `    ${key}: ${nestedInterfaceName};\n`;
      subInterfaces += generateTypeScriptInterface(value, nestedInterfaceName);
    } else if (Array.isArray(value) && value.length > 0) {
      const elementType = capitalizeFirstLetter(key) + 'Item';
      result += `    ${key}: ${elementType}[];\n`;
      if (typeof value[0] === 'object' && value[0] !== null) {
        subInterfaces += generateTypeScriptInterface(value[0], elementType);
      }
    } else {
      const type = getTypeScriptType(value);
      result += `    ${key}: ${type};\n`;
    }
  }
  
  result += '}\n\n';
  return result + subInterfaces;
};

// 辅助函数
const getJavaType = (value: any): string => {
  if (typeof value === 'string') return 'String';
  if (typeof value === 'number') return Number.isInteger(value) ? 'int' : 'double';
  if (typeof value === 'boolean') return 'boolean';
  if (Array.isArray(value)) {
    if (value.length > 0) {
      return `List<${getJavaType(value[0])}>`;
    }
    return 'List<Object>';
  }
  if (typeof value === 'object' && value !== null) return 'Object';
  return 'Object';
};

const getGoType = (value: any): string => {
  if (typeof value === 'string') return 'string';
  if (typeof value === 'number') return Number.isInteger(value) ? 'int' : 'float64';
  if (typeof value === 'boolean') return 'bool';
  if (Array.isArray(value)) {
    if (value.length > 0) {
      return `[]${getGoType(value[0])}`;
    }
    return '[]interface{}';
  }
  if (typeof value === 'object' && value !== null) return 'struct{}';
  return 'interface{}';
};

const getTypeScriptType = (value: any): string => {
  if (typeof value === 'string') return 'string';
  if (typeof value === 'number') return 'number';
  if (typeof value === 'boolean') return 'boolean';
  if (Array.isArray(value)) {
    if (value.length > 0) {
      return `${getTypeScriptType(value[0])}[]`;
    }
    return 'any[]';
  }
  if (typeof value === 'object' && value !== null) return 'object';
  return 'any';
};

const capitalizeFirstLetter = (str: string): string => {
  return str.charAt(0).toUpperCase() + str.slice(1);
};

const copyToClipboard = async () => {
  try {
    await navigator.clipboard.writeText(outputClass.value);
    alert('代码已复制到剪贴板');
  } catch (err) {
    alert('复制失败，请手动复制');
  }
};
</script>

<style scoped>
.json-to-class-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.tool-wrapper {
  display: flex;
  gap: 20px;
  height: 500px;
  align-items: stretch;
}

.input-section,
.output-section {
  flex: 1;
  min-width: 0; /* 防止内容溢出 */
}

.input-textarea,
.output-textarea {
  width: 100%;
  height: 100%;
  padding: 15px;
  border: 1px solid #ccc;
  border-radius: 8px;
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  resize: none;
}

.button-group {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 20px;
  min-width: 150px; /* 设置最小宽度 */
  padding: 0 10px; /* 添加内边距 */
  margin-left: 30px;
}

.language-select {
  padding: 12px;
  border-radius: 6px;
  border: 1px solid #ccc;
  background-color: white;
  font-size: 14px;
  width: 100%; /* 使选择框宽度充满容器 */
}

.convert-button {
  padding: 12px 24px;
  background-color: #007BFF;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.3s;
  width: 100%; /* 使按钮宽度充满容器 */
}

.convert-button:hover {
  background-color: #0056b3;
}

.output-section {
  flex: 1;
  background-color: #f5f5f5;
  padding: 15px;
  border-radius: 8px;
  overflow: auto;
}

pre {
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
  background-color: transparent !important;
  padding: 0 !important;
}

code {
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  display: block;
  white-space: pre-wrap;
  text-align: left;
}

.copy-button {
  padding: 12px 24px;
  background-color: #28a745;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.3s;
  width: 100%;
  margin-top: 10px;
}

.copy-button:hover {
  background-color: #218838;
}

.toast {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background-color: #323232;
  color: white;
  padding: 12px 24px;
  border-radius: 4px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  animation: fadeInOut 2s ease-in-out;
  z-index: 1000;
}

@keyframes fadeInOut {
  0% {
    opacity: 0;
    transform: translateX(-50%) translateY(20px);
  }
  10% {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
  90% {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
  100% {
    opacity: 0;
    transform: translateX(-50%) translateY(20px);
  }
}
</style>